package gamemaster;

import java.util.ArrayList;
import java.util.Hashtable;

import communication.message.Player;
import communication.message.Point;

/***
 * 
 * @author Łukasz Wrzesiński
 * 
 */

public class Rules {

	private Hashtable<String, Play> plays;

	public boolean checkEnd(String id) {
		Point from = new Point(0, 0);
		Play play = null;
		if ((play = plays.get(id)) != null) {
			from = play.getBoard().getPoints()
					.get(play.getBoard().getPoints().size() - 1);
		}
		if (Math.abs(from.getX()) <= 1 && Math.abs(from.getY()) == 6)
			return true;
		return false;
	}

	public boolean checkMoves(ArrayList<Point> to, String id) {
		for (int i = 0; i < to.size(); i++) {
			if (i < to.size() - 1)
				if (!canBounce(to.get(i), id))
					return false;
			if (canBounce(to.get(to.size() - 1), id))
				return false;
			Point from = new Point(0, 0);
			if(i==0){
				Play play = null;
				if ((play = plays.get(id)) != null) {
					from = play.getBoard().getPoints()
							.get(play.getBoard().getPoints().size() - 1);
				}
			}
			else {
				from=to.get(i-1);
			}
			if (!moveCorrect(from, to.get(i), id))
				return false;
		}
		// dodaj ruch do board
		Play play = null;
		if ((play = plays.get(id)) != null) {
			for (Point p : to)
				play.getBoard().addPoint(p);
			play.setCurrentPlayer((play.getCurrentPlayer() + 1) % 2);
		}
		return true;
	}

	private boolean isInBounds(Point from, Point to) {
		if (Math.abs(to.getX()) > 4
				|| (Math.abs(to.getY()) > 6 && Math.abs(to.getX()) <= 1))
			return false;
		if (Math.abs(to.getX()) > 1 && Math.abs(to.getY()) > 5)
			return false;
		if (Math.abs(to.getX()) == 4 && Math.abs(from.getX()) == 4)
			return false;
		if (Math.abs(to.getY()) == 5 && Math.abs(from.getY()) == 5
				&& Math.abs(from.getX()) > 1 && Math.abs(to.getY()) > 1)
			return false;
		return true;
	}

	private boolean moveExists(Point from, Point to, String id) {
		Play currentPlay = new Play();
		Play play = null;
		if ((play = plays.get(id)) != null)
			currentPlay = play;
		Point previousPoint = new Point(0, 0);
		for (Point p : currentPlay.getBoard().getPoints()) {
			if (p.equals(from) && previousPoint.equals(to) || p.equals(to)
					&& previousPoint.equals(from))
				return true;
			previousPoint = p;
		}
		return false;
	}

	private boolean canBounce(Point to, String id) {
		if (Math.abs(to.getX()) == 4
				|| (Math.abs(to.getY()) == 5 && Math.abs(to.getX()) != 0))
			return true;
		Play currentPlay = new Play();
		Play play = null;
		if ((play = plays.get(id)) != null)
			currentPlay = play;
		if (currentPlay.getBoard().getPoints().contains(to))
			return true;
		return false;
	}

	public boolean moveCorrect(Point from, Point to, String id) {
		if (Math.abs(from.getX() - to.getX()) > 1
				|| Math.abs(from.getY() - to.getY()) > 1)
			return false;
		if (!isInBounds(from, to))
			return false;
		if (moveExists(from, to, id))
			return false;
		return true;
	}

	public void addPlay(ArrayList<Player> _players, String _playId) {
		Play p = new Play(_players, _playId);
		plays.put(_playId, p);
	}

	public void removePlay(String playId) {
		Play currentPlay = new Play();
		Play play = null;
		if ((play = plays.get(playId)) != null)
			currentPlay = play;
		plays.remove(currentPlay);
	}

	public Rules() {
		plays = new Hashtable<String, Play>();
	}

	public Hashtable<String, Play> getPlays() {
		return plays;
	}

}
